iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0
Modern Web

一起來玩圖像編輯器:Fabric.js 的實戰修煉系列 第 17

Day17-fabric.js 進階組合技!想要在畫布範圍之外的控制點也可以被看到

  • 分享至 

  • xImage
  •  

你曾經有,放進去的圖片過大,結果超過畫布範圍,沒有控制點可以拉的窘境嗎?
或是想要畫布的圖形有出血效果,卻難以判斷圖形究竟已經超出邊框多少嗎?

您的救星來了!
在畫布外可以看見控制點的做法!
day17-demo

而輸出的圖片像這樣,就跟想輸出的尺寸一樣:
https://ithelp.ithome.com.tw/upload/images/20240820/20168354gThHZDYlcA.jpg
(微錯誤示範XD 這張圖在下載時忘記把 clipPath 加上 strokeWidth: 0 屬性,已導致左邊上邊出現黑線🌚,想避免此情況請看後續說明喔 )

到底是怎麼做的呢?
方法其實不難,讓我們來一探究竟~


這段程式碼的構成構想如下:

這裡我們把最終想輸出的區塊稱為 工作區 好了

  • 創建一個全螢幕大小的 canvas,並在上面設置 controlsAboveOverlay: true
    在 canvas 中心設置一個 300x400 的 clipPath,這就是你的 工作區 (你可以設置任何你最終想輸出的尺寸)。
  • 使用者可以在整個 canvas 上繪圖和操作物件,但只有 工作區 範圍內的物件會顯示在畫布上,因為他在 clipPath 遮罩之內,在 工作區 之外的地方只會顯示控制點。
  • 提供一個 onDownloadImage 函數,只導出 工作區 內的內容,使用的方式是用與當初設置 工作區 clipPath 一樣的參數(位置、大小、位移等)。

這樣就能無痛擁有控制點了~

  1. 獲取畫布元素,初始化 Fabric.js 畫布
    !!!畫布須設置 controlsAboveOverlay: true 讓控制點得以顯現在 clipPath 的畫面以外

    const canvasEl = document.getElementById("canvas");
    const canvas = new fabric.Canvas(canvasEl, {
      backgroundColor: "#fff",
      controlsAboveOverlay: true  // 要達成這個效果的重要設置
     //要讓物件控制項(邊框/控制項)在覆蓋圖像之上渲染。
    });
    
  2. 計算畫布中心點
    抓到畫布中心才能以此為基準,讓每次畫布都在視窗中心

    var centerX = canvas.width / 2;
    var centerY = canvas.height / 2;
    
  3. 設置導出畫布的配置
    重要!要在 clipPath 上設置 strokeWidth: 0,不然輸出圖左跟上邊會有黑邊,並且些微偏移(請見上面的錯誤示範輸出圖XD)

    const exportCanvasConfig = {
    left: centerX*0.2,
    top: centerY*0.2,
    width: centerX*0.6,
    height: centerY*0.6,
    strokeWidth: 0 //這邊要設定 0 !
    };
    
  4. 設置畫布大小為全螢幕

    function resizeCanvas() {
     canvas.setWidth(window.innerWidth);
     canvas.setHeight(window.innerHeight);
     updateClipPath();
    }
    
  5. 創建並更新 clipPath

    function updateClipPath() {
      var clipPath = new fabric.Rect(exportCanvasConfig); //依據設定檔來設置 clipPath
      canvas.clipPath = clipPath;
      canvas.renderAll();
    }
    
  6. 監聽視窗大小變化
    因為畫布在設定時是隨著視窗尺寸變動的,所以每次改變視窗尺寸時也要跟著調整 canvas 大小。

    window.addEventListener("resize", resizeCanvas);
    
  7. 添加導出按鈕並設置點擊事件

    const onDownloadImage = () => {
      const data = canvas.toDataURL({
        ...exportCanvasConfig, //使用和 clipPath 相同大小位置的設定
        format: "jpeg",
        quality: 1,
      });
      const a = document.createElement("a");
      a.href = data;
      a.download = "my-draw.jpg";
      a.click();
    };
    document.getElementById("download").addEventListener("click", onDownloadImage);
    

今日🌰:fabric.js 畫布外的控制點


上一篇
Day16-fabric.js 進階組合技!自定義控件開發 (control) 實例
下一篇
Day18-fabric.js 進階組合技! 畫布縮放與平移:實現像 illustrator 一樣的縮放和拖動功能
系列文
一起來玩圖像編輯器:Fabric.js 的實戰修煉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言